package com.todod.aspect;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.todod.common.util.RandomNumber;
import com.todod.service.IDataLogService;

import net.sf.json.JSONObject;

/**
 * 记录数据日志
 *
 * @ClassName: DataLogAspect
 * @Description:
 * @author gsh
 * @date 2019年10月11日
 *
 */
@Component
@Aspect
public class DataLogAspect {

	Logger log = LoggerFactory.getLogger(this.getClass());

	private final static String INNER_LOG = "1";
	private final static String UPDATE_LOG = "2";
	private final static String DELETE_LOG = "3";

	@Autowired
	private IDataLogService dataLogService;

	/**
	 * 保存数据日志
	 *
	 * @Title: insertDataLog
	 * @Description:
	 * @author gsh
	 * @date 2019年10月11日
	 * @param jp
	 * @throws Throwable
	 */
	@AfterReturning(value = "execution(* com.todod.mapper.*.*(..))&& !execution(* com.todod.mapper.DataLogMapper.*(..))&& !execution(* com.todod.mapper.OperateLogMapper.*(..))")
	public void insertDataLog(JoinPoint jp) throws Throwable {
		Object[] args = jp.getArgs();// 参数

		MethodSignature methodSignature = (MethodSignature) jp.getSignature();
		Method method = methodSignature.getMethod();

		if (method.getName().startsWith("get")) {
			return;
		}
		if (method.getName().startsWith("select")) {
			return;
		}

		// 获取用户
		RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
		if (requestAttributes == null)
			return;
		HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();

		Object _userId = request.getAttribute("_userId"); // 操作人
		if (_userId == null) {
			return;
		}
		Object _dataLogPici = request.getAttribute("_dataLogPici"); // 批次
		if (_dataLogPici == null) {
			_dataLogPici = RandomNumber.getInstance().getGenerageNumber();
			request.setAttribute("_dataLogPici", _dataLogPici);
		}

		Type[] types = AopUtils.getTargetClass(jp.getTarget()).getGenericInterfaces(); // getGenericInterfaces方法能够获取类/接口实现的所有接口
		if (types.length == 0) {
			return;
		}
		String typeName = types[0].getTypeName();
		String TableName = getTable(typeName);// 实体名称

		String type = ""; // 类型
		String content = ""; // 数据内容
		String zhuId = "";

		// 记录数据日志，只记录insert，updateById,update,deleteById,deleteByMap,delete,deleteBatchIds
		if ("insert".equals(method.getName())) {
			if (args.length < 1)
				return;
			Object object = args[0];
			JSONObject jo = JSONObject.fromObject(object);
			content = jo.toString();
			zhuId = jo.optString("id") != null ? jo.optString("id").toString() : "";

			type = INNER_LOG;
		} else if ("updateById".equals(method.getName())) {
			Object object = args[0];
			JSONObject jo = JSONObject.fromObject(object);
			content = jo.toString();
			zhuId = jo.optString("id") != null ? jo.optString("id").toString() : "";

			type = UPDATE_LOG;
		} else if ("update".equals(method.getName())) {
			Object object = args[0];
			JSONObject jo = JSONObject.fromObject(object);
			content = jo.toString();
			zhuId = jo.optString("id") != null ? jo.optString("id").toString() : "";

			type = UPDATE_LOG;
		} else if ("deleteById".equals(method.getName())) {
			Object object = args[0];
			JSONObject jo = JSONObject.fromObject(object);
			content = jo.toString();
			zhuId = jo.optString("id") != null ? jo.optString("id").toString() : "";

			type = DELETE_LOG;
		} else if ("deleteByMap".equals(method.getName())) {
			Object object = args[0];
			JSONObject jo = JSONObject.fromObject(object);
			content = jo.toString();
			zhuId = jo.optString("id") != null ? jo.optString("id").toString() : "";

			type = DELETE_LOG;
		} else if ("delete".equals(method.getName())) {
			Object object = args[0];
			JSONObject jo = JSONObject.fromObject(object);
			content = jo.toString();
			zhuId = jo.optString("id") != null ? jo.optString("id").toString() : "";

			type = DELETE_LOG;
		} else if ("deleteBatchIds".equals(method.getName())) {
			Object object = args[0];
			JSONObject jo = JSONObject.fromObject(object);
			content = jo.toString();
			zhuId = jo.optString("id") != null ? jo.optString("id").toString() : "";

			type = DELETE_LOG;
		} else {
			return;
		}

		dataLogService.saveData(_userId, _dataLogPici.toString(), TableName, type, content, zhuId);
	}

	// 使用反射技术得到T的真实类型
	private Class getRealType(Class clazz) {
		// 获取当前new的对象的泛型的父类类型
		ParameterizedType pt = (ParameterizedType) clazz.getGenericSuperclass();
		// 获取第一个类型参数的真实类型
		return (Class) pt.getActualTypeArguments()[0];
	}

	/**
	 * 获取mapeer前
	 *
	 * @Title: getTable
	 * @Description:
	 * @author gsh
	 * @date 2019年10月28日
	 * @param name
	 * @return
	 */
	private String getTable(String name) {
		// com.todod.mapper.InterfaceErrorLogMapper
		if (StringUtils.isBlank(name)) {
			return name;
		}
		String[] split = name.split("\\.");
		if (split.length == 0) {
			return name;
		}
		String className = split[split.length - 1];
		String table = className.replaceAll("Mapper", "");

		return table;
	}

}
